在Python 3.5.0上:
>>> from collections import namedtuple >>> cluster = namedtuple('Cluster', ['a', 'b']) >>> c = cluster(a=4, b=9) >>> c Cluster(a=4, b=9) >>> vars(c) OrderedDict([('a', 4), ('b', 9)])
在Python 3.5.1上:
>>> from collections import namedtuple >>> cluster = namedtuple('Cluster', ['a', 'b']) >>> c = cluster(a=4, b=9) >>> c Cluster(a=4, b=9) >>> vars(c) Traceback (most recent call last): File "", line 1, in TypeError: vars() argument must have __dict__ attribute
似乎有些事情发生了namedtuple
变化(或者可能是某些事情vars()
?).
这是故意的吗?我们不应该使用这种模式将命名元组转换为字典吗?
每个Python bug#24931:
[
__dict__
]消失了,因为它在Python 3中从根本上被破坏了,因此必须将其删除.提供__dict__
破坏子类化并产生奇怪的行为.
进行更改的修订版
具体来说,没有__slots__
定义的子类会表现得很奇怪:
>>> Cluster = namedtuple('Cluster', 'x y') >>> class Cluster2(Cluster): pass >>> vars(Cluster(1,2)) OrderedDict([('x', 1), ('y', 2)]) >>> vars(Cluster2(1,2)) {}
使用._asdict()
.
来自文档
命名的元组实例没有每个实例的字典,因此它们是轻量级的,并且不需要比常规元组更多的内存.
该 文档(和help(namedtuple)
)说,使用c._asdict()
转换为一个字典.
__dict__
被实施为@property
已被删除; 你可以看到源代码的变化:
3.5.0:
def __repr__(self): 'Return a nicely formatted representation string' return self.__class__.__name__ + '({repr_fmt})' % self @property def __dict__(self): 'A new OrderedDict mapping field names to their values' return OrderedDict(zip(self._fields, self)) def _asdict(self): 'Return a new OrderedDict which maps field names to their values.' return self.__dict__ def __getnewargs__(self): 'Return self as a plain tuple. Used by copy and pickle.' return tuple(self) def __getstate__(self): 'Exclude the OrderedDict from pickling' return None
3.5.1:
def __repr__(self): 'Return a nicely formatted representation string' return self.__class__.__name__ + '({repr_fmt})' % self def _asdict(self): 'Return a new OrderedDict which maps field names to their values.' return OrderedDict(zip(self._fields, self)) def __getnewargs__(self): 'Return self as a plain tuple. Used by copy and pickle.' return tuple(self)